home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-07-09 | 7.5 KB | 316 lines | [TEXT/CWIE] |
- // MSAECompare.c
- //
- // Original version by Jon Lansdell and Nigel Humphreys.
- // 4.0 and 3.1 updates by Greg Sutton.
- // ©Apple Computer Inc 1996, all rights reserved.
-
- /*
- Changes for 4.0
-
- 29-Feb-96 : GS : Added ability to compare menu and menu item properties.
- 22-Apr-96 : GS : Comparing text begins, ends, and contains is now true if equal.
- */
-
- #include "MSAECompare.h"
-
- #include <AEPackObject.h>
- #include "MSGlobals.h"
- #include "MSUtils.h"
- #include "MSAEUtils.h"
- #include "MSWindow.h"
- #include "MSFile.h"
- #include "MSAppleEvents.h"
-
- #include "MSToken.h"
- #include "MSAECountElements.h"
- #include "MSAEGetData.h"
-
- #include <string.h>
-
-
- #pragma segment AppleEvent
-
-
- OSErr InstallObjectCallbacks(void)
- {
- OSErr err;
-
- err = AESetObjectCallbacks(NewOSLCompareProc(MyCompareProc),
- NewOSLCountProc(MyCountProc),
- NULL, NULL, NULL, NULL, NULL);
-
- return(err);
- }
-
-
- pascal OSErr MyCompareProc(DescType oper, const AEDesc* obj1, const AEDesc* obj2, Boolean* result)
- {
- AEDesc desc1 = {typeNull, NULL};
- AEDesc desc2 = {typeNull, NULL};
- AEDesc tempDesc = {typeNull, NULL};
- OSErr err;
-
- err = ExtractData(obj1, &desc1);
- if (err != noErr) goto done;
- err = ExtractData(obj2, &desc2);
- if (err != noErr) goto done;
-
- // Make sure the 2 data types are the same
- if (desc1.descriptorType != desc2.descriptorType)
- {
- err = AEDuplicateDesc(&desc2, &tempDesc);
- if (err != noErr) goto done;
- err = AEDisposeDesc(&desc2);
- err = AECoerceDesc(&tempDesc, desc1.descriptorType, &desc2);
- if (err != noErr) // If we can't coerce one way, try
- { // the opposite way.
- err = AEDuplicateDesc(&tempDesc, &desc2); // We disposed of desc2
- err = AEDisposeDesc(&tempDesc);
- err = AEDuplicateDesc(&desc1, &tempDesc);
- if (err != noErr) goto done;
- err = AEDisposeDesc(&desc1);
- err = AECoerceDesc(&tempDesc, desc2.descriptorType, &desc1);
- if (err != noErr) goto done;
- }
- }
-
- // Now that we know that the 2 types are the same, go ahead and run the compare
- switch(desc1.descriptorType)
- {
- case typeChar:
- err = MyCompareText(oper, &desc1, &desc2, result);
- break;
-
- case typeShortInteger:
- case typeLongInteger:
- err = MyCompareInteger(oper, &desc1, &desc2, result);
- break;
-
- case typeBoolean:
- err = MyCompareBoolean(oper, &desc1, &desc2, result);
- break;
-
- default:
- err = errAEWrongDataType;
- }
-
- done:
- if (desc1.dataHandle)
- (void) AEDisposeDesc(&desc1);
- if (desc2.dataHandle)
- (void) AEDisposeDesc(&desc2);
- if (tempDesc.dataHandle)
- (void) AEDisposeDesc(&tempDesc);
-
- return(err);
- }
-
-
- OSErr ExtractData(const AEDesc *sourceDesc, AEDesc *theData)
- {
- AEDesc intermediateDesc = {typeNull, NULL};
- OSErr err;
-
- // This routine can receive: An Object specifier, an object token, a property token, or
- // some data (TEXT, Rectangle, etc.). It needs to convert whatever it's handed into data
- // and return that.
-
- // If we don't have any data, complain
- if (sourceDesc->descriptorType == typeNull || sourceDesc->dataHandle == NULL)
- return(errAENoSuchObject);
-
- // If it's an object specifier, resolve into a token
- if (sourceDesc->descriptorType == typeObjectSpecifier)
- err = AEResolve(sourceDesc, kAEIDoMinimum, &intermediateDesc);
- else // Otherwise, just copy it
- err = AEDuplicateDesc(sourceDesc, &intermediateDesc);
-
- if (err != noErr) goto done;
-
- // Now that we have a token, read from it
- switch (intermediateDesc.descriptorType)
- {
- case typeMyApplProp:
- case typeMyTextProp:
- case typeMyWindowProp:
- case typeMyMenuProp:
- case typeMyMenuItemProp:
- case typeMyText:
- err = HandleGetData(&intermediateDesc, typeWildCard, theData);
- break;
-
- default:
- // This is probably raw data , so pass it back up the line
- err = AEDuplicateDesc(&intermediateDesc, theData);
- }
-
- done:
- if (intermediateDesc.dataHandle)
- (void) AEDisposeDesc(&intermediateDesc);
-
- return(err);
- }
-
-
- OSErr MyCompareText(DescType oper, const AEDesc *desc1, const AEDesc *desc2, Boolean *result)
- {
- int compareResult;
- long compareSize;
- long textSize1, textSize2;
- char *testStr, *compareStr;
- OSErr err = noErr;
-
- textSize1 = GetHandleSize(desc1->dataHandle);
- HLockHi(desc1->dataHandle);
- textSize2 = GetHandleSize(desc2->dataHandle);
- HLockHi(desc2->dataHandle);
- if (textSize1 < textSize2)
- {
- switch (oper)
- {
- case kAEBeginsWith: // Can't begin or end or contain any string
- case kAEEndsWith: // longer than itself
- case kAEContains:
- *result = false;
- return(noErr);
- }
-
- compareSize = textSize1;
- }
- else
- compareSize = textSize2;
-
- switch (oper)
- {
- case kAEEndsWith: // Offset to end of string
- testStr = (char *)(*desc1->dataHandle + textSize1 - textSize2);
- break;
-
- case kAEContains:
- testStr = NewPtr(textSize1 + 1);
- BlockMove(*desc1->dataHandle, testStr, textSize1);
- testStr[textSize1] = '\0';
- compareStr = NewPtr(textSize2 + 1);
- BlockMove(*desc2->dataHandle, compareStr, textSize2);
- compareStr[textSize2] = '\0';
- *result = (NULL != strstr(testStr,compareStr));
- DisposePtr(testStr);
- DisposePtr(compareStr);
- return(noErr);
-
- default:
- testStr = (char *)*desc1->dataHandle;
- }
-
- compareResult = strncmp(testStr, (char *)*desc2->dataHandle, compareSize);
-
- HUnlock(desc1->dataHandle);
- HUnlock(desc2->dataHandle);
-
- switch (oper)
- {
- case kAEEquals:
- *result = (textSize1 == textSize2 && compareResult == 0);
- break;
-
- case kAEBeginsWith:
- case kAEEndsWith:
- *result = (compareResult == 0);
- break;
-
- case kAELessThan:
- *result = (compareResult < 0);
- break;
-
- case kAELessThanEquals:
- *result = (compareResult <= 0);
- break;
-
- case kAEGreaterThan:
- *result = (compareResult > 0);
- break;
-
- case kAEGreaterThanEquals:
- *result = (compareResult >= 0);
- break;
-
- default:
- err = errAEBadTestKey;
- }
-
- return(err);
- }
-
-
- OSErr MyCompareInteger(DescType oper, const AEDesc *desc1, const AEDesc *desc2, Boolean *result)
- {
- long num1, num2;
- AEDesc longDesc = {typeNull, NULL};
- OSErr err;
-
- // Make each number is a long integer (in case it's a short integer) before extracting the data
- err = AECoerceDesc(desc1, typeLongInteger, &longDesc);
- if (err != noErr) goto done;
- num1 = **(long **)longDesc.dataHandle;
- (void) AEDisposeDesc(&longDesc); // We're done with longDesc, so dispose of it
- longDesc.dataHandle = NULL; // Mark this as disposed
-
- err = AECoerceDesc(desc2, typeLongInteger, &longDesc);
- if (err != noErr) goto done;
- num2 = **(long **)longDesc.dataHandle;
- // No need to dispose of this descriptor, as the code at "done" will do it for us
-
- switch (oper)
- {
- case kAEEquals:
- *result = (num1 == num2);
- break;
-
- case kAELessThan:
- *result = (num1 < num2);
- break;
-
- case kAELessThanEquals:
- *result = (num1 <= num2);
- break;
-
- case kAEGreaterThan:
- *result = (num1 > num2);
- break;
-
- case kAEGreaterThanEquals:
- *result = (num1 >= num2);
- break;
-
- default:
- err = errAEBadTestKey;
- }
-
- done:
- if (longDesc.dataHandle)
- (void) AEDisposeDesc(&longDesc);
-
- return err;
- } // MyCompareInteger
-
-
- OSErr MyCompareBoolean (DescType oper, const AEDesc *desc1, const AEDesc *desc2, Boolean *result)
- {
- Boolean bool1, bool2;
- OSErr err = noErr;
-
- // Apple events defines a boolean as a 1-byte value containing 1 for TRUE and 0 for FALSE
- // We'll use a test to convert this into C's boolean notation, just to make this easier to
- // debug
-
- bool1 = (**(char **)desc1->dataHandle) != 0;
- bool2 = (**(char **)desc2->dataHandle) != 0;
-
- if (oper == kAEEquals)
- *result = (bool1 == bool2);
- else
- err = errAEBadTestKey; // No other tests make sense
-
- return err;
- } // MyCompareBoolean
-